package src;

import src.Base.*;
import src.Base.Error;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.attribute.FileAttribute;
import java.util.ArrayList;
import java.util.Objects;

public class Parse {
    ArrayList<Word> words;
    private Word sym; //当前单词
    private SyntaxWord head;//语法树头结点
    private ArrayList<String> res;
    private int index; //读指针
    public Parse(ArrayList<Word> words){
        this.words = words;
        this.index = 0;
        res = new ArrayList<>();
    }
    public void analyze(){
        nextSym();
        head = CompUnit();
    }
    private SyntaxWord CompUnit(){
        SyntaxWord compUnit = createMiddle("CompUnit");
        while(isDecl()){
            compUnit.addChild(Decl());
        }
        while((symTpyeCheck(sym, WordType.INTTK) && !symTpyeCheck(getNextWord(), WordType.MAINTK))||symTpyeCheck(sym, WordType.VOIDTK)){
            // int开头函数名非main或void开头为函数
            // System.out.println(sym.getContent()+" GOTOFuncDef");
            compUnit.addChild(FuncDef());
        }
        compUnit.addChild(MainFuncDef());
        res.add("<CompUnit>");
        return compUnit;
    }

    private SyntaxWord MainFuncDef() { // int main ()
        SyntaxWord mainFuncDef = createMiddle("MainFuncDef");
        if(symTpyeCheck(sym, WordType.INTTK)){ //int
            mainFuncDef.addChild(createTerminal(sym));
            nextSym();
            if(symTpyeCheck(sym, WordType.MAINTK)){//main
                mainFuncDef.addChild(createTerminal(sym));
                nextSym();
                if(symTpyeCheck(sym, WordType.LPARENT) && symTpyeCheck(getNextWord(), WordType.RPARENT)){
                    //()
                    mainFuncDef.addChild(createTerminal(sym));
                    nextSym();
                    mainFuncDef.addChild(createTerminal(sym));
                    nextSym();
                    mainFuncDef.addChild(Block());
                }else{
                    //error
                }
            }else{
                //error
            }
        }else{
            //error
        }
        res.add("<MainFuncDef>");
        return mainFuncDef;
    }

    private SyntaxWord Decl(){// Decl → ConstDecl | VarDecl
        SyntaxWord decl = createMiddle("Decl");
        if(symTpyeCheck(sym, WordType.CONSTTK)){
            decl.addChild(ConstDecl());
        }else if(symTpyeCheck(sym, WordType.INTTK)){
            //System.out.println("gotoVarDecl " + sym.getContent());
            decl.addChild(VarDecl());
        }else{
            //e
        }
        return decl;
    }

    private SyntaxWord VarDecl() {// int a
        //VarDecl → BType VarDef { ',' VarDef } ';'
        SyntaxWord varDecl  = createMiddle("VarDecl");
        if(symTpyeCheck(sym, WordType.INTTK)){//BType
            varDecl.addChild(createTerminal(sym));
            nextSym();
            varDecl.addChild(VarDef());
            while (symTpyeCheck(sym, WordType.COMMA)){
                varDecl.addChild(createTerminal(sym));
                nextSym();
                varDecl.addChild(VarDef());
            }
            if(symTpyeCheck(sym, WordType.SEMICN)){
                varDecl.addChild(createTerminal(sym));
                nextSym();
            }else{
                //e
                ErrorLog.instance.addError(getPreWordLine(), "i");
            }
        }
        res.add("<VarDecl>");
        return varDecl;
    }

    private SyntaxWord VarDef() {
        /*VarDef → Ident { '[' ConstExp ']' }
            | Ident { '[' ConstExp ']' } '=' InitVal
         */
        SyntaxWord varDef = createMiddle("VarDef");
        if(symTpyeCheck(sym, WordType.IDENFR)){//Ident
            varDef.addChild(createTerminal(sym));
            nextSym();
            while(symTpyeCheck(sym, WordType.LBRACK)){//[
                varDef.addChild(createTerminal(sym));
                nextSym();
                varDef.addChild(ConstExp());//CONstExp
                if(!symTpyeCheck(sym, WordType.RBRACK)){// 无]
                 //e
                    ErrorLog.instance.addError(getPreWordLine(), "k");
                }else {
                    varDef.addChild(createTerminal(sym));
                    nextSym();
                }
            }
            if (symTpyeCheck(sym, WordType.ASSIGN)){//Ident { '[' ConstExp ']' } '=' InitVal
                varDef.addChild(createTerminal(sym));
                nextSym();
                varDef.addChild(InitVal());
            }
        }else {
            //e
        }
        res.add("<VarDef>");
        return varDef;
    }

    private SyntaxWord InitVal() {
        // InitVal → Exp | '{' [ InitVal { ',' InitVal } ]'}'
        SyntaxWord initVal = createMiddle("InitVal");
        if(symTpyeCheck(sym, WordType.LBRACE)){
            initVal.addChild(createTerminal(sym));
            nextSym();
            if (symTpyeCheck(sym, WordType.RBRACE)){//{}
                initVal.addChild(createTerminal(sym));
                nextSym();
            }else{// '{' InitVal { ',' InitVal } '}'
                initVal.addChild(InitVal());
                while(symTpyeCheck(sym, WordType.COMMA)){
                    initVal.addChild(createTerminal(sym));
                    nextSym();
                    initVal.addChild(InitVal());
                }
                if(symTpyeCheck(sym, WordType.RBRACE)){
                    addTerminal(initVal);
                }else {
                    //e
                }
            }
        }else {
            initVal.addChild(Exp());
        }
        res.add("<InitVal>");
        return initVal;
    }

    private SyntaxWord ConstDecl() {
        //ConstDecl → 'const' BType ConstDef { ',' ConstDef } ';'
        SyntaxWord constDecl = createMiddle("ConstDecl");
        if(symTpyeCheck(sym, WordType.CONSTTK) && symTpyeCheck(getNextWord(), WordType.INTTK)){
            constDecl.addChild(createTerminal(sym));//const
            nextSym();
            constDecl.addChild(createTerminal(sym));//int
            nextSym();
            constDecl.addChild(ConstDef());
            while(symTpyeCheck(sym, WordType.COMMA)){
                // const int a,b,c;
                constDecl.addChild(createTerminal(sym));
                nextSym();
                constDecl.addChild(ConstDef());
            }
            if(symTpyeCheck(sym, WordType.SEMICN)){//;
                constDecl.addChild(createTerminal(sym));
                nextSym();
            }else{
                //e
                ErrorLog.instance.addError(getPreWordLine(), "i");
            }
        }else{
            //e
        }
        res.add("<ConstDecl>");
        return constDecl;
    }

    private SyntaxWord ConstDef() {
        // ConstDef → Ident { '[' ConstExp ']' } '=' ConstInitVal
        SyntaxWord constDef = createMiddle("ConstDef");
        if(symTpyeCheck(sym, WordType.IDENFR)){
            constDef.addChild(createTerminal(sym));
            nextSym();
            while(symTpyeCheck(sym, WordType.LBRACK)){// [
                constDef.addChild(createTerminal(sym));
                nextSym();
                constDef.addChild(ConstExp());
                if(symTpyeCheck(sym, WordType.RBRACK)){// ]
                    constDef.addChild(createTerminal(sym));
                    nextSym();
                }else{// 无]
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "k");
                }
            }
            if(symTpyeCheck(sym, WordType.ASSIGN)){// =
                constDef.addChild(createTerminal(sym));
                nextSym();
                constDef.addChild(ConstInitVal());
            }else{
                //e
            }
        }
        res.add("<ConstDef>");
        return constDef;
    }

    private SyntaxWord ConstInitVal() {
        //ConstInitVal → ConstExp | '{' [ ConstInitVal { ',' ConstInitVal } ] '}' /
        SyntaxWord ci = createMiddle("ConstInitVal");
        if(symTpyeCheck(sym, WordType.LBRACE)){
            SyntaxWord tmp = createTerminal(sym);
            ci.addChild(tmp);
            nextSym();
            if(!symTpyeCheck(sym, WordType.RBRACE)){
                ci.addChild(ConstInitVal());
                while(symTpyeCheck(sym, WordType.COMMA)){
                    ci.addChild(createTerminal(sym));
                    nextSym();
                    ci.addChild(ConstInitVal());
                }
                addTerminal(ci);
            }else{// sym = }
                ci.addChild(createTerminal(sym));
                nextSym();
            }
        }else{
            ci.addChild(ConstExp());
        }
        res.add("<ConstInitVal>");
        return ci;
    }

    private SyntaxWord ConstExp() {
        SyntaxWord constExp = createMiddle("ConstExp");
        constExp.addChild(AddExp());
        res.add("<ConstExp>");
        return constExp;
    }

    private SyntaxWord AddExp() {

        // AddExp → MulExp | AddExp ('+' | '−') MulExp 2 + 3*3
        SyntaxWord addExp = createMiddle("AddExp");
        SyntaxWord Father = null;
        SyntaxWord preAddExp = null;
        addExp.addChild(MulExp());
        boolean f_Flag = false;
        if(symTpyeCheck(sym, WordType.PLUS) || symTpyeCheck(sym, WordType.MINU)){
            preAddExp = addExp;
            f_Flag = true;
        }
        while (symTpyeCheck(sym, WordType.PLUS) || symTpyeCheck(sym, WordType.MINU)){
            Father = createMiddle("AddExp");
            Father.addChild(preAddExp);
            res.add("<AddExp>");
            Father.addChild(createTerminal(sym));// + -
            nextSym();
            Father.addChild(MulExp());
            preAddExp = Father;
        }
        res.add("<AddExp>");
        if (f_Flag) {
            if(Father == null){
                System.out.println("null add in Parse exit");
                System.exit(-1);
            }
            return Father;
        }
        return addExp;
    }
/*
    private SyntaxWord AddExp() {

        // AddExp → MulExp | AddExp ('+' | '−') MulExp 2 + 3*3
        SyntaxWord addExp = createMiddle("AddExp");
        SyntaxWord Father = createMiddle("AddExp");
        addExp.addChild(MulExp());
        boolean f_Flag = false;
        while (symTpyeCheck(sym, WordType.PLUS) || symTpyeCheck(sym, WordType.MINU)){
            f_Flag = true;
            Father.addChild(addExp);
            res.add("<AddExp>");
            Father.addChild(createTerminal(sym));// + -
            nextSym();
            Father.addChild(MulExp());
        }
        res.add("<AddExp>");
        if (f_Flag) {
            return Father;
        }
        return addExp;
    }
 */
    private SyntaxWord MulExp() {
        //MulExp → UnaryExp | MulExp ('*' | '/' | '%') UnaryExp
        SyntaxWord mulExp = createMiddle("MulExp");
        SyntaxWord Father = null;
        SyntaxWord preMulExp = null;
        mulExp.addChild(UnaryExp());
        boolean f_flag = false;
        if(symTpyeCheck(sym, WordType.MULT) || symTpyeCheck(sym, WordType.DIV) || symTpyeCheck(sym, WordType.MOD)){
            preMulExp = mulExp;
            f_flag = true;
        }
        while (symTpyeCheck(sym, WordType.MULT) || symTpyeCheck(sym, WordType.DIV) || symTpyeCheck(sym, WordType.MOD)){
            //若当前单词后有 */% 则其应有一MulExp父节点
            Father = createMiddle("MulExp");
            Father.addChild(preMulExp);
            res.add("<MulExp>");
            Father.addChild(createTerminal(sym));//* % /
            nextSym();
            Father.addChild(UnaryExp());
            preMulExp = Father;
        }
        res.add("<MulExp>");
        if(f_flag){
            if(Father == null){
                System.out.println("null in mul Parse exit");
                System.exit(-1);
            }
            return Father;
        }
        return mulExp;
    }

    private SyntaxWord UnaryExp() {
        //UnaryExp → PrimaryExp | Ident '(' [FuncRParams] ')'| UnaryOp UnaryExp
        SyntaxWord unaryExp = createMiddle("UnaryExp");
        if(symTpyeCheck(sym,WordType.LPARENT)){//PrimaryExp::=(Exp)
            unaryExp.addChild(PrimaryExp());
        }else if(symTpyeCheck(sym, WordType.IDENFR)){// Ident
            if(!symTpyeCheck(getNextWord(),WordType.LPARENT)){
                unaryExp.addChild(PrimaryExp());
            }else{//函数情况 func(a,b) func()
                unaryExp.addChild(createTerminal(sym));//函数名
                nextSym();
                unaryExp.addChild(createTerminal(sym));//(
                nextSym();
                if (!symTpyeCheck(sym, WordType.RPARENT)){//有参数
                    unaryExp.addChild(FuncRParams());
                }
                if(symTpyeCheck(sym, WordType.RPARENT)){//无参数
                    unaryExp.addChild(createTerminal(sym));
                    nextSym();
                }else{
                    ErrorLog.instance.addError(getPreWordLine(),"j");
                    unaryExp.getChildren().remove(2);
                }
            }
        } else if (symTpyeCheck(sym, WordType.INTCON)) {
            unaryExp.addChild(PrimaryExp());
        } else if (symTpyeCheck(sym, WordType.PLUS) ||
                symTpyeCheck(sym, WordType.MINU)||
                symTpyeCheck(sym, WordType.NOT)){
                unaryExp.addChild(UnaryOp());
                res.add("<UnaryOp>");
                unaryExp.addChild(UnaryExp());
        }else {
            //e
        }
        res.add("<UnaryExp>");
        return unaryExp;
    }

    private SyntaxWord UnaryOp() {// + * !
        SyntaxWord op = createMiddle("UnaryOp");
        op.addChild(createTerminal(sym));
        nextSym();
        return op;
    }

    /***
     * 函数实参表
     * @return 函数实参节点
     */
    private SyntaxWord FuncRParams() {
        // b = func(a,1);
        // FuncRParams → Exp { ',' Exp }
        SyntaxWord funcRParams = createMiddle("FuncRParams");
        funcRParams.addChild(Exp());
        while(symTpyeCheck(sym, WordType.COMMA)){
            funcRParams.addChild(createTerminal(sym));
            nextSym();
            funcRParams.addChild(Exp());
        }
        res.add("<FuncRParams>");
        return funcRParams;
    }

    /**
     * 函数形参表
     * @return 函数形参表节点
     */
    private SyntaxWord FuncFParams() {
        // int func(int a, int b);
        //FuncFParams → FuncFParam { ',' FuncFParam }
        SyntaxWord funcFParams = createMiddle("FuncFParams");
        funcFParams.addChild(FuncFParam());
        while(symTpyeCheck(sym, WordType.COMMA)){
            funcFParams.addChild(createTerminal(sym));
            nextSym();
            funcFParams.addChild(FuncFParam());
        }
        res.add("<FuncFParams>");
        return funcFParams;
    }

    /***
     * 函数形参
     * @return 函数参形节点
     */
    private SyntaxWord FuncFParam(){
        //FuncFParam → BType Ident ['[' ']' { '[' ConstExp ']' }]
        SyntaxWord funFParam = createMiddle("FuncFParam");
        if(symTpyeCheck(sym, WordType.INTTK)){//BType
            funFParam.addChild(createTerminal(sym));
            nextSym();
        }else{
            //e
            System.exit(353);
        }
        if(symTpyeCheck(sym,WordType.IDENFR)){
            addTerminal(funFParam);
            if(symTpyeCheck(sym, WordType.LBRACK)){// [
                addTerminal(funFParam);
                if (symTpyeCheck(sym, WordType.RBRACK)){// ]
                    addTerminal(funFParam);// int a[];
                }else {
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "k");
                }
                //{ '[' ConstExp ']' }
                while(symTpyeCheck(sym, WordType.LBRACK)){
                    addTerminal(funFParam);
                    funFParam.addChild(ConstExp());
                    if(symTpyeCheck(sym, WordType.RBRACK)){
                        addTerminal(funFParam);
                    }else{
                        ErrorLog.instance.addError(getPreWordLine(), "k");
                    }
                }
            }
            res.add("<FuncFParam>");
        }else {
            //e
        }
        return funFParam;
    }
    private SyntaxWord Exp() {
        SyntaxWord exp = createMiddle("Exp");
        exp.addChild(AddExp());
        res.add("<Exp>");
        return exp;
    }

    private SyntaxWord PrimaryExp() {
        //PrimaryExp → '(' Exp ')' | LVal | Number
        SyntaxWord primaryExp = createMiddle("PrimaryExp");
        if (symTpyeCheck(sym, WordType.LPARENT)){//(Exp)
            primaryExp.addChild(createTerminal(sym));
            nextSym();
            primaryExp.addChild(Exp());
            if(symTpyeCheck(sym, WordType.RPARENT)){
                primaryExp.addChild(createTerminal(sym));
                nextSym();
            }else{
                //e
            }
        }else if(symTpyeCheck(sym, WordType.INTCON)){//Number
            primaryExp.addChild(NumBer());
        }else if(symTpyeCheck(sym, WordType.IDENFR)){// LVAL
            primaryExp.addChild(LVAL());
        }
        res.add("<PrimaryExp>");
        return primaryExp;
    }

    private SyntaxWord LVAL() {
        SyntaxWord lval = createMiddle("LVal");
        // LVal → Ident {'[' Exp ']'}
        if(symTpyeCheck(sym, WordType.IDENFR)){
            lval.addChild(createTerminal(sym));
            nextSym();
            // a[2][2]
            while (symTpyeCheck(sym, WordType.LBRACK)){//[
                lval.addChild(createTerminal(sym));
                nextSym();
                lval.addChild(Exp());
                if(!symTpyeCheck(sym, WordType.RBRACK)){//不为]
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "k");
                }else{
                    lval.addChild(createTerminal(sym));
                    nextSym();
                }
            }
        }else{
            //e
        }
        res.add("<LVal>");
        return lval;
    }
    private SyntaxWord NumBer() {
        //Number
        //  ↓
        // numberToken
        SyntaxWord num = createMiddle("NumBer");
        num.addChild(createTerminal(sym));
        nextSym();
        res.add("<Number>");
        return num;
    }

    private SyntaxWord FuncDef(){
        // FuncDef → FuncType Ident '(' [FuncFParams] ')' Block
        SyntaxWord funcDef = createMiddle("FuncDef");
        funcDef.addChild(FuncType());
        //log("MYLOG:");
        //log();
        if(symTpyeCheck(sym, WordType.IDENFR)){
            funcDef.addChild(createTerminal(sym));
            nextSym();
            if (symTpyeCheck(sym, WordType.LPARENT)){//(
                funcDef.addChild(createTerminal(sym));
                nextSym();
                if (symTpyeCheck(sym, WordType.RPARENT)){//()
                    funcDef.addChild(createTerminal(sym));
                    nextSym();
                } else if (symTpyeCheck(sym, WordType.LBRACE)) {
                    ErrorLog.instance.addError(getPreWordLine(),"j");
                } else {// FuncFParams存在
                    //log("SMY:");
                    //log();
                    funcDef.addChild(FuncFParams());
                    if(symTpyeCheck(sym, WordType.RPARENT)){//结尾)
                        funcDef.addChild(createTerminal(sym));
                        nextSym();
                    }else{
                        //e
                        ErrorLog.instance.addError(getPreWordLine(), "j");
                    }
                }
                funcDef.addChild(Block());
            }
            //log(sym.getContent() + " line:"+sym.getLine());
            res.add("<FuncDef>");
        }else {
            //e
        }
        return funcDef;
    }


    private SyntaxWord FuncType() {
        //FuncType → 'void' | 'int'
        SyntaxWord funcType = createMiddle("FuncType");
        if(Objects.equals(sym.getContent(), "void") || Objects.equals(sym.getContent(), "int")){
            funcType.addChild(createTerminal(sym));
            nextSym();
            res.add("<FuncType>");
        }else{
            //e
        }
        return funcType;
    }

    private SyntaxWord Block(){
        // Block → '{' { BlockItem } '}'
        SyntaxWord block = createMiddle("Block");
        if(symTpyeCheck(sym, WordType.LBRACE)){
            block.addChild(createTerminal(sym));
            nextSym();
            if(symTpyeCheck(sym, WordType.RBRACE)){ //{} 空代码块
                block.addChild(createTerminal(sym));
                nextSym();
            }else {
                while(!symTpyeCheck(sym, WordType.RBRACE)){
                    block.addChild(BlockItem());
                }
                if(symTpyeCheck(sym, WordType.RBRACE)){// 结尾}
                    block.addChild(createTerminal(sym));
                    nextSym();
                }
            }

        }
        res.add("<Block>");
        return block;
    }

    private SyntaxWord BlockItem(){
        //BlockItem → Decl | Stmt
        SyntaxWord blockItem = createMiddle("BlockItem");
        if (symTpyeCheck(sym, WordType.INTTK)){
            blockItem.addChild(Decl());
        }else if(symTpyeCheck(sym, WordType.CONSTTK)){
            blockItem.addChild(Decl());
        }else{
            blockItem.addChild(Stmt());
        }
        return blockItem;
    }

    private SyntaxWord Stmt() {
        SyntaxWord stmt = createMiddle("Stmt");
        //IF
        if (symTpyeCheck(sym, WordType.IFTK)){
            //'if' '(' Cond ')' Stmt [ 'else' Stmt ]
            stmt.setStmtType("If");
            stmt.addChild(createTerminal(sym));
            nextSym();
            if(symTpyeCheck(sym, WordType.LPARENT)){// (
                stmt.addChild(createTerminal(sym));
                nextSym();
                stmt.addChild(Cond());
                if(symTpyeCheck(sym, WordType.RPARENT)){
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                }else{
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "j");
                }
                stmt.addChild(Stmt());
                if(symTpyeCheck(sym, WordType.ELSETK)){
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                    stmt.addChild(Stmt());
                }
            }
        }
        //FOR
        else if(symTpyeCheck(sym, WordType.FORTK)){
            int [] forElements = {-1,-1,-1};
            // 'for' '(' [ForStmt] ';' [Cond] ';' [forStmt] ')' Stmt
            stmt.setStmtType("Loop");
            stmt.addChild(createTerminal(sym));//for
            nextSym();
            if(symTpyeCheck(sym, WordType.LPARENT)){
                stmt.addChild(createTerminal(sym));// (
                nextSym();
                //当前为(,下一个可能为ForStmt, ';'
                /*
                0 0 0
                0 0 1
                0 1 0
                0 1 1
                1 0 0
                1 0 1
                1 1 0
                1 1 1
                 */

                if (symTpyeCheck(sym, WordType.SEMICN)) {// ForStmt为空
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                    if(symTpyeCheck(sym, WordType.SEMICN)){//Cond为空
                        stmt.addChild(createTerminal(sym)); //第二个；
                        nextSym();
                        if(symTpyeCheck(sym, WordType.RPARENT)){//forStmt为空
                            //结尾)
                            stmt.addChild(createTerminal(sym));// 0 0 0
                            forElements = new int[]{0, 0, 0};
                            nextSym();
                        }else{
                            stmt.addChild(forStmt());//(;;forStmt) 0 0 1 fengk
                            if(symTpyeCheck(sym, WordType.RPARENT)){
                                addTerminal(stmt);
                                forElements = new int[]{0, 0, 1};
                            }else{
                                //e
                            }
                        }
                    }else{
                        stmt.addChild(Cond());// 0 1 ?
                        if(symTpyeCheck(sym, WordType.SEMICN)){// cond后 ;
                            stmt.addChild(createTerminal(sym));
                            nextSym();
                        }
                        if(symTpyeCheck(sym, WordType.RPARENT)){// cond;后无forStmt
                            stmt.addChild(createTerminal(sym));
                            forElements = new int[]{0, 1, 0};
                            nextSym();// 0 1 0
                        }else {
                            stmt.addChild(forStmt());// 0 1 1  fengk
                            if(symTpyeCheck(sym, WordType.RPARENT)){
                                forElements = new int[]{0, 1, 1};
                                addTerminal(stmt);
                            }else{
                                //e
                            }
                        }
                    }
                }else{// ForStmt存在  (For;?;?)
                    stmt.addChild(ForStmt());//1 ? ?
                    if(symTpyeCheck(sym, WordType.SEMICN)){// ForStmt后 ;
                        stmt.addChild(createTerminal(sym));
                        nextSym();
                    }
                    //?;?)
                    if(symTpyeCheck(sym, WordType.SEMICN)){
                        //SAME
                        stmt.addChild(createTerminal(sym));// 1 0 ?
                        nextSym();
                        //for是否存在
                        if(symTpyeCheck(sym, WordType.RPARENT)){//forStmt不存在
                            stmt.addChild(createTerminal(sym));//1 0 0
                            forElements = new int[]{1, 0, 0};
                            nextSym();
                        }else{// 1 1 1
                            stmt.addChild(forStmt());
                            if(symTpyeCheck(sym, WordType.RPARENT)) {//forStmt后)
                                stmt.addChild(createTerminal(sym));//1 0 1
                                forElements = new int[]{1, 0, 1};
                                nextSym();
                            }else{
                                //e
                            }
                        }
                        //
                    }else{// 1 1 ?
                        //SAME
                        stmt.addChild(Cond());//DIFFERENT
                        if(symTpyeCheck(sym, WordType.SEMICN)) {// cond 后;
                            stmt.addChild(createTerminal(sym));
                            nextSym();
                            // ?)
                            if(symTpyeCheck(sym, WordType.RPARENT)){//forStmt不存在
                                stmt.addChild(createTerminal(sym));//1 1 0
                                forElements = new int[]{1, 1, 0};
                                nextSym();
                            }else{// 1 1 1
                                stmt.addChild(forStmt());
                                if(symTpyeCheck(sym, WordType.RPARENT)) {//forStmt后)
                                    stmt.addChild(createTerminal(sym));//1 1 1
                                    forElements = new int[]{1, 1, 1};
                                    nextSym();
                                }else{
                                    //e
                                }
                            }
                        }
                        //
                    }

                }
            }
            stmt.setForElements(forElements);
            stmt.addChild(Stmt());

        }
        //Break;
        else if(symTpyeCheck(sym,WordType.BREAKTK)){
            stmt.addChild(createTerminal(sym));
            stmt.setStmtType("Break");
            nextSym();
            if(symTpyeCheck(sym, WordType.SEMICN)){
                stmt.addChild(createTerminal(sym));
                nextSym();
            }else{
                ErrorLog.instance.addError(getPreWordLine(), "i");
            }
        }
        //Continue;
        else if(symTpyeCheck(sym,WordType.CONTINUETK)){
            stmt.addChild(createTerminal(sym));
            stmt.setStmtType("Continue");
            nextSym();
            if(symTpyeCheck(sym, WordType.SEMICN)){
                stmt.addChild(createTerminal(sym));
                nextSym();
            }else{
                //e
                ErrorLog.instance.addError(getPreWordLine(), "i");
            }
        }
        //return [Exp];
        else if(symTpyeCheck(sym,WordType.RETURNTK)){
            stmt.addChild(createTerminal(sym));
            stmt.setStmtType("Return");
            nextSym();
            if (symTpyeCheck(sym, WordType.SEMICN)){//无Exp
                stmt.addChild(createTerminal(sym));
                nextSym();
            }else{//有Exp
                stmt.addChild(Exp());
                if (symTpyeCheck(sym, WordType.SEMICN)){
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                }else {
                    ErrorLog.instance.addError(getPreWordLine(), "i");
                }
            }
        }
        //Block
        else if (symTpyeCheck(sym, WordType.LBRACE)) {
            stmt.addChild(Block());
            stmt.setStmtType("Block");
        }
        // printf
        else if (symTpyeCheck(sym, WordType.PRINTFTK)) {
            //'printf''('FormatString{','Exp}')'';'
            stmt.addChild(createTerminal(sym));//printf
            stmt.setStmtType("Output");
            nextSym();
            if(symTpyeCheck(sym, WordType.LPARENT)){
                stmt.addChild(createTerminal(sym));
                nextSym();
                stmt.addChild(FormatString());
                while(symTpyeCheck(sym, WordType.COMMA)){
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                    stmt.addChild(Exp());
                }
                if(symTpyeCheck(sym, WordType.RPARENT)){
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                }else{//无)
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "j");
                }
                if(symTpyeCheck(sym, WordType.SEMICN)){
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                }else {//无;
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "i");
                }
            }else{ //不为 (
                //e
            }
        }
        // Exp ';' || LVal
        else if (isExp()) {
            stmt.addChild(Exp());
            if(symTpyeCheck(sym, WordType.SEMICN)){
                stmt.addChild(createTerminal(sym));
                nextSym();
            }else{
                //e
            }
        }
        // [Exp]; || LVal = Exp;
        else if (symTpyeCheck(sym, WordType.IDENFR)) {
            int resNowSize = res.size();
            int oldIndex = index;
            SyntaxWord tmp = LVAL();
            if (symTpyeCheck(sym, WordType.ASSIGN)){//存在= ,为LVal = 情况，tmp为LVAl
                stmt.addChild(tmp);
                stmt.addChild(createTerminal(sym));
                nextSym();
                // LVal = getint()
                if(symTpyeCheck(sym,WordType.GETINTTK)){
                    stmt.setStmtType("Input");
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                    if(symTpyeCheck(sym, WordType.LPARENT)){//(
                        stmt.addChild(createTerminal(sym));
                        nextSym();
                        if (symTpyeCheck(sym, WordType.RPARENT)){//)
                            stmt.addChild(createTerminal(sym));
                            nextSym();
                            if (symTpyeCheck(sym, WordType.SEMICN)){//;
                                stmt.addChild(createTerminal(sym));
                                nextSym();
                            }else {
                                ErrorLog.instance.addError(getPreWordLine(), "i");
                            }
                        }else{
                            ErrorLog.instance.addError(getPreWordLine(), "j");
                        }
                    }
                }else{// LVal = Exp;
                    stmt.setStmtType("Assignment");
                    stmt.addChild(Exp());
                    if (symTpyeCheck(sym, WordType.SEMICN)){
                        stmt.addChild(createTerminal(sym));
                        nextSym();
                    }else{
                        ErrorLog.instance.addError(getPreWordLine(), "i");
                    }

                }
            }else{//不存在=,为Exp;情况
                /*
                当前:
                Exp <- LVal
                ;   sym
                ??? index
                * */
                back(resNowSize, oldIndex);//回退当前指针与添加的结果res
                stmt.setStmtType("Exp");
                stmt.addChild(Exp());
                if(symTpyeCheck(sym, WordType.SEMICN)){//;
                    stmt.addChild(createTerminal(sym));
                    nextSym();
                }else{
                    //e
                    ErrorLog.instance.addError(getPreWordLine(), "i");
                }
            }
        }
        // 无Exp，仅有;
        else if(symTpyeCheck(sym, WordType.SEMICN)){
            //log();
            stmt.addChild(createTerminal(sym));
            nextSym();
        }
        res.add("<Stmt>");
        return stmt;
    }

    private void back(int oldSize, int oldIndex) {
        //LVal可能为a,a[][],不可仅回退一个单词
        int nowSize = res.size();
        for(int i = nowSize - 1; i >= oldSize; i--){
            //System.out.println("remove:"+res.get(i));
            res.remove(i);
        }
        index = oldIndex - 1;//index - (index - oldIndex + 1)
        //index = index - 2; //仅考虑单个词情况，未考虑如array[1],此时oldIndex = index - 1
        nextSym();
    }

    private boolean isExp() {
        if(symTpyeCheck(getNextWord(), WordType.ASSIGN)){
            return false;
        }
        return symTpyeCheck(sym,WordType.INTCON)||symTpyeCheck(sym, WordType.LPARENT)||symTpyeCheck(sym, WordType.PLUS)||
                symTpyeCheck(sym, WordType.MINU)||symTpyeCheck(sym, WordType.NOT);
    }

    private SyntaxWord FormatString() {
        //TODO
        SyntaxWord formatString = createTerminal(sym);
        if(sym.getType().equals("STRCON")){
            nextSym();
        }else{
            //e
        }
        return formatString;
    }

    private SyntaxWord ForStmt() {
        // ForStmt → LVal '=' Exp
        SyntaxWord forStmt = createMiddle("ForStmt");
        if(symTpyeCheck(sym, WordType.IDENFR)){
            forStmt.addChild(LVAL());
            if(symTpyeCheck(sym, WordType.ASSIGN)){
                forStmt.addChild(createTerminal(sym));
                nextSym();
                forStmt.addChild(Exp());
            }
        }
        res.add("<ForStmt>");
        return  forStmt;
    }

    private SyntaxWord forStmt() {
        return ForStmt();
    }

    private SyntaxWord Cond(){
        //Cond → LOrExp
        SyntaxWord cond = createMiddle("Cond");
        cond.addChild(LOrExp());
        res.add("<Cond>");
        return cond;
    }

    private SyntaxWord LOrExp() {
        // LOrExp → LAndExp | LOrExp '||' LAndExp
        SyntaxWord lOrExp = createMiddle("LOrExp");
        SyntaxWord Father = null;
        SyntaxWord preLOrExp = null;
        lOrExp.addChild(LAndExp());
        boolean f_flag = false;
        if(symTpyeCheck(sym, WordType.OR)){
            preLOrExp = lOrExp;
            f_flag = true;
        }
        while(symTpyeCheck(sym, WordType.OR)){
            Father = createMiddle("LOrExp");
            Father.addChild(preLOrExp);
            res.add("<LOrExp>");
            Father.addChild(createTerminal(sym)); // ||
            nextSym();
            Father.addChild(LAndExp());
            preLOrExp = Father;
        }
        res.add("<LOrExp>");
        if(f_flag){
            if(Father == null){
                System.out.println("null LOrExp in Parse");
                System.exit(-1);
            }
            return Father;
        }
        return lOrExp;
    }

    private SyntaxWord LAndExp() {
        //LAndExp → EqExp | LAndExp '&&' EqExp
        SyntaxWord lAndExp = createMiddle("LAndExp");
        SyntaxWord Father = null;
        SyntaxWord preLandExp = null;
        lAndExp.addChild(EqExp());
        boolean f_flag = false;
        if(symTpyeCheck(sym, WordType.AND)){
            preLandExp = lAndExp;
            f_flag = true;
        }
        while(symTpyeCheck(sym, WordType.AND)){
            Father = createMiddle("LAndExp");
            Father.addChild(preLandExp);
            res.add("<LAndExp>");
            Father.addChild(createTerminal(sym)); // &&
            nextSym();
            Father.addChild(EqExp());
            preLandExp = Father;
        }
        res.add("<LAndExp>");
        if (f_flag){
            if(Father == null){
                System.out.println("null LAndExp in Parse exit");
                System.exit(-1);
            }
            return Father;
        }
        return lAndExp;
    }

    private SyntaxWord EqExp() {
        // EqExp → RelExp | EqExp ('==' | '!=') RelExp
        SyntaxWord eqExp = createMiddle("EqExp");
        SyntaxWord Father = null;
        SyntaxWord preEqExp = null;
        eqExp.addChild(RelExp());
        boolean f_flag = false;
        if(symTpyeCheck(sym, WordType.NEQ) || symTpyeCheck(sym, WordType.EQL)){
            preEqExp = eqExp;
            f_flag = true;
        }
        while(symTpyeCheck(sym, WordType.NEQ) || symTpyeCheck(sym, WordType.EQL)){
            Father = createMiddle("EqExp");
            Father.addChild(preEqExp);
            res.add("<EqExp>");
            Father.addChild(createTerminal(sym)); // == !=
            nextSym();
            Father.addChild(RelExp());
            preEqExp = Father;
        }
        res.add("<EqExp>");
        if (f_flag){
            if(Father == null){
                System.out.println("error null in EqExp Parse");
                System.exit(-1);
            }
            return Father;
        }
        return eqExp;
    }

    private SyntaxWord RelExp() {
        //RelExp → AddExp | RelExp ('<' | '>' | '<=' | '>=') AddExp
        SyntaxWord relExp = createMiddle("RelExp");
        SyntaxWord Father = null;
        SyntaxWord preRelExp = null;
        relExp.addChild(AddExp());
        boolean f_flag = false;
        if(isRelSym(sym)){
            preRelExp = relExp;
            f_flag = true;
        }
        while(isRelSym(sym)){
            Father = createMiddle("RelExp");
            Father.addChild(relExp);
            res.add("<RelExp>");
            Father.addChild(createTerminal(sym)); // < > <= >=
            nextSym();
            Father.addChild(AddExp());
            preRelExp = Father;
        }
        res.add("<RelExp>");
        if (f_flag){
            if(Father == null){
                System.out.println("error null in RelExp Parse");
                System.exit(-1);
            }
            return Father;
        }
        return relExp;
    }
    private boolean isRelSym(Word sym){
        return(Objects.equals(sym.getType(), WordType.LSS.toString())) || (sym.getType() == WordType.LEQ.toString()) || (Objects.equals(sym.getType(), WordType.GRE.toString())) || (Objects.equals(sym.getType(), WordType.GEQ.toString()));
    }
    private void nextSym(){
        if(index >= words.size()){
            return;
        }
        sym = words.get(index);
        //Mylog:System.out.println("read:"+sym.getContent()+" line:"+sym.getLine());
        //res.add("<read:"+sym.getContent()+"line:"+sym.getLine()+">");
        //String ans = sym.getType() + " " + sym.getContent();
        //res.add(ans);
        index++;
    }
    private boolean isDecl(){
        Word nxt = getNextWord();
        Word nnxt = getNnxtWord();
        //System.out.println("now:"+sym.getContent()+"nxt:"+nxt.getContent() + " nnxt:"+nnxt.getContent());
        return (symTpyeCheck(sym, WordType.CONSTTK) ||
                (!symTpyeCheck(nxt, WordType.MAINTK) &&
                        symTpyeCheck(sym, WordType.INTTK) &&
                        !symTpyeCheck(nnxt, WordType.LPARENT)));
    }
    private boolean symTpyeCheck(Word word, WordType wordType){
        if(word == null){
            return false;
        }
        return word.getType().equals(wordType.toString());
    }
    private boolean isEnd(){
        return index >= words.size();
    }
    private Word getNextWord(){//查看下一个单词
        if (isEnd()){
            return null;
        }else{
            return words.get(index);
        }
    }
    private Word getNnxtWord(){//查看下下个单词
        if (isEnd()){
            return null;
        }else{
            return words.get(index + 1);
        }
    }
    /***
     *创建终结符节点
     * @param word 符号实例,包含其种类与值
     * @return 语法树节点
     */
    private SyntaxWord createTerminal (Word word){
        //System.out.println("log:" + word.getType() + " "+word.getContent());
        res.add(word.getType() + " "+word.getContent());
        return new SyntaxWord(null, word);
    }

    /***
     *
     * @param type 该字符类型
     * @return 语法树节点
     */
    private SyntaxWord createMiddle (String type){
        return new SyntaxWord(type, null);
    }
    public void printRes(){
        for (String tmp:res){
            System.out.println(tmp);
        }
    }
    private void addTerminal(SyntaxWord node){
        node.addChild(createTerminal(sym));
        nextSym();
    }
    private void log(){
        res.add("log: line:"+sym.getLine() + " content:"+sym.getContent());
    }
    private void log(String msg){
        res.add(msg);
    }

    public void writeRes(){
        for(String s:res){
            Writer.instance.write("output.txt", s + "\n");
            // System.out.println(s);
        }
    }
    public SyntaxWord getHead(){
        return head;
    }
    private int getPreWordLine(){
        Word tmp = words.get(index - 2);
        return tmp.getLine();
    }
}
